package com.zjmzxfzhl.common.util;


import cn.hutool.core.img.ImgUtil;
import com.zjmzxfzhl.common.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * Created by jiafe on 2018/5/9.
 */
@Component
@Slf4j
public class FileUtil {

    public static final String TYPE_BMP = "bmp";
    public static final String TYPE_GIF = "gif";
    public static final String TYPE_JPG = "jpg";
    public static final String TYPE_JPEG = "jpeg";
    public static final String TYPE_PNG = "png";
    public static final String TYPE_TXT = "txt";
    public static final String TYPE_HTML = "html";
    public static final String TYPE_PDF = "pdf";
    public static final String TYPE_DOC = "doc";
    public static final String TYPE_DOCX = "docx";
    public static final String TYPE_XLS = "xls";
    public static final String TYPE_XLSX = "xlsx";
    public static final String TYPE_JAR = "jar";

    public static List<String> ALLOWED_TYPES = Arrays.asList(TYPE_JPEG, TYPE_JPG, TYPE_PNG, TYPE_PDF, TYPE_JAR);
    private static final String DEFAULT_DECIMAL_FROMAT = "0.00";
    private static final int CONSTANT_1024 = 1024;
    private static final int CONSTANT_512 = 512;
    private static final int CONSTANT_306 = 306;
    private static final float MIN_SCALE = 0.40F;
    private static final String UNIT_GB = "GB";
    private static final String UNIT_MB = "MB";
    private static final String UNIT_KB = "KB";
    private static final String UNIT_B = "B";
    private static final String DEFAULT_PATH = "default";
    private static final String TEMP_PATH = "temp";


    public static boolean isImage(String fileOriginalName) {
        String type = StringUtils.getFilenameExtension(fileOriginalName);
        if (TYPE_JPG.equalsIgnoreCase(type)
                || TYPE_JPEG.equalsIgnoreCase(type)
                || TYPE_PNG.equalsIgnoreCase(type)) {
            return true;
        }
        return false;
    }

    public static File scaleFit(File srcImgFile, String fileOriginalName, String fileSize) {
        File dstFile = null;
        //设定压缩后的大小300kb
        if (fileSize.contains(UNIT_MB)) {
            //压缩
            float size = Float.parseFloat(fileSize.substring(0, fileSize.length() - 3));
            float scale = 1.0F / (float) Math.sqrt(size * CONSTANT_1024 / CONSTANT_512);
            //设置scal 最小值,//针对大体积图片，调整缩放比例
            scale = scale < MIN_SCALE ? MIN_SCALE : scale;
            System.out.println("缩放比例：" + scale);
            dstFile = doScaleImg(srcImgFile, fileOriginalName, scale);
        } else if (fileSize.contains(UNIT_KB)) {
            float size = Float.parseFloat(fileSize.substring(0, fileSize.length() - 3));
            if (size > CONSTANT_306) {
                //压缩
                float scale = 1.0F / (float) Math.sqrt(size / CONSTANT_306);
                dstFile = doScaleImg(srcImgFile, fileOriginalName, scale);
                System.out.println("缩放比例：" + scale);
            }
        }
        return dstFile;
    }

    public static File doScaleImg(File srcImgFile, String fileOriginalName, float scale) {
        File scaledImgFile = PathUtil.getDefaultFile("scaled_" + fileOriginalName);
        ImgUtil.scale(srcImgFile, scaledImgFile, scale);
        return scaledImgFile;
    }

    public static String getFileSize(File file) {
        DecimalFormat df = new DecimalFormat(DEFAULT_DECIMAL_FROMAT);
        if (file.exists()) {
            double bytes = file.length();
            double kilobytes = (bytes / CONSTANT_1024);
            double megabytes = (kilobytes / CONSTANT_1024);
            double gigabytes = (megabytes / CONSTANT_1024);

            if (gigabytes > 1) {
                //返回 单位GB
                return df.format(gigabytes) + UNIT_GB;
            } else if (megabytes > 1) {
                //返回单位 MB
                return df.format(megabytes) + UNIT_MB;
            } else if (kilobytes > 1) {
                //返回单位 KB
                return df.format(kilobytes) + UNIT_KB;
            } else {
                //返回单位 B
                return bytes + UNIT_B;
            }
        } else {
            throw new AppException("文件不存在");
        }
    }


    /**
     * 根据文件原始名称，获取一个随机名称：xxx-xx...x-xxxx.txt
     *
     * @param fileOriginalName
     * @return
     */
    public String getFileRandomName(String fileOriginalName) {
        String extension = StringUtils.getFilenameExtension(fileOriginalName);
        String resourceId = UUID.randomUUID().toString();
        if (StringUtils.isEmpty(extension)) {
            return resourceId;
        } else {
            return resourceId + "." + extension;
        }
    }

    public String checkFileExtension(String fileOriginalName) {
        String extension = StringUtils.getFilenameExtension(fileOriginalName);
        if (!ALLOWED_TYPES.contains(extension.toLowerCase())) {
            throw new AppException(MessageFormat.format("文件后缀:{0}不合规，参考：{1}", extension, ALLOWED_TYPES));
        }
        return extension;
    }


    public static boolean deleteFile(File file) {
        if (null != file && file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * 删除文件
     */
    public static boolean deleteFile(String resourcePath) {
        File targetFile = new File(resourcePath);
        return deleteFile(targetFile);
    }

    /**
     * 获取默认路径
     *
     * @return
     */
    public String getDefaultRootPath() {
        String rootJarPath = getBaseJarPath().getAbsolutePath();
        File defaultFile = new File(rootJarPath + File.separator + DEFAULT_PATH);
        if (!defaultFile.exists()) {
            if (!defaultFile.mkdirs()) {
                throw new AppException("创建默认存放路径失败");
            }
        }
        return defaultFile.getAbsolutePath();
    }

    /**
     * 获取临时文件存放路径
     *
     * @return
     */
    public String getTempPath() {
        String rootPath = getBaseJarPath().getAbsolutePath();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        File tempFile = new File(rootPath + File.separator + TEMP_PATH);
        if (!tempFile.exists()) {
            if (!tempFile.mkdirs()) {
                throw new AppException("创建临时目录失败");
            }
        }
        return tempFile.getAbsolutePath();
    }

    public File getBaseJarPath() {
        ApplicationHome home = new ApplicationHome(getClass());
        File jarFile = home.getSource();
        return jarFile.getParentFile();
    }

    /**
     * 将文件写入输出流
     *
     * @param os
     * @param file
     */
    public static void doExport(OutputStream os, File file, String fileExtenstion, Boolean deleteAfter) {
        byte[] buff = new byte[StreamUtils.BUFFER_SIZE];
        BufferedInputStream bis = null;
        XSSFWorkbook workbook = null;
        XWPFDocument xdoc = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            if (TYPE_XLSX.equalsIgnoreCase(fileExtenstion)) {
                workbook = new XSSFWorkbook(bis);
                workbook.write(os);
            } else if (TYPE_DOCX.equalsIgnoreCase(fileExtenstion)) {
                xdoc = new XWPFDocument(bis);
                xdoc.write(os);
            } else {
                int i = bis.read(buff);
                while (i != -1) {
                    os.write(buff, 0, buff.length);
                    os.flush();
                    i = bis.read(buff);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            if (xdoc != null) {
                try {
                    xdoc.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (deleteAfter) {
                cn.hutool.core.io.FileUtil.del(file);
            }
        }
    }

    public static void setDownloadResponse(HttpServletResponse response, File file, String fileName) {
        setDownloadResponse(response, file, fileName, false);
    }

    public static void setPreviewResponse(HttpServletResponse response, File file, String fileName) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "max-age=60");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        try {
            response.setContentType(Files.probeContentType(file.toPath()));
            response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            doExport(response.getOutputStream(), file, StringUtils.getFilenameExtension(fileName), false);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void setDownloadResponse(HttpServletResponse response, File file, String fileName, Boolean deleteAfter) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "no-cache");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        try {
            String contentType = Files.probeContentType(file.toPath());
            response.setContentType(contentType);
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            doExport(response.getOutputStream(), file, StringUtils.getFilenameExtension(fileName), deleteAfter);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
